home *** CD-ROM | disk | FTP | other *** search
- page 96,132
- ;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
- ;§ §
- ;§ ディレクトリエントリ ソート ユーティリティ §
- ;§ §
- ;§ DSORT.EXE Ver1.30 §
- ;§ §
- ;§ Copyright (C) by 福地 邦雄 1991-1992. All rights reserved. §
- ;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
- .MODEL SMALL,C
- ;
- DPB struc
- drivenumber db ? ;ドライブ番号
- unitnumber db ? ;ユニット番号
- sectorlength dw ? ;セクタ長
- sectorperalloc db ? ;1クラスタ当たりのセクタ数-1
- shiftcount db ? ;1クラスタ当たりのセクタ数の2のべき乗
- reservedsector dw ? ;先頭のリザーブセクタ数
- numberoffat db ? ;FAT数
- directoryentry dw ? ;ルートディレクトリのエントリ数
- datastartsector dw ? ;データ領域開始セクタ番号
- datasector dw ? ;最大クラスタ番号(全クラスタ数+1)
- fatsector dw ? ;1FAT当たりのセクタ数
- directorystart dw ? ;ディレクトリ領域開始セクタ番号
- deviceheader dd ? ;デバイスヘッダへのポインタ
- mediadescriptor db ? ;メディアディスクリプタ
- diskchange db ? ;ディスクの交換可能属性
- tonextdpb dd ? ;次のDPBへのポインタ
- currentcluster dw ? ;カレントクラスタ
- reserved db 3 dup(?) ;リザーブ
- DPB ends
- ;
- DPB3 struc
- DPB3reserv db 15 DUP(?) ;ドライブ番号~最大クラスタ番号
- D3fatsector db ? ;1FAT当たりのセクタ数
- D3directorystart dw ? ;ディレクトリ領域開始セクタ番号
- D3deviceheader dd ? ;デバイスヘッダへのポインタ
- D3mediadescriptor db ? ;メディアディスクリプタ
- D3diskchange db ? ;ディスクの交換可能属性
- D3tonextdpb dd ? ;次のDPBへのポインタ
- D3currentcluster dw ? ;カレントクラスタ
- D3reserved dd ? ;リザーブ
- DPB3 ends
- ;
- DEVHEAD struc
- nextdevice dd ? ; 次のデバイスヘッダへのポインタ
- deviceattr dw ? ; デバイス属性
- strategy dw ? ; ストラテジエントリオフセット
- intrentry dw ? ; 割り込みエントリオフセット
- devicename db 8 dup(?) ; デバイス名/ドライブ数
- DEVHEAD ends
- ;
- DSKPACKET struc
- sectornum dd ? ; 32bitセクタ番号
- rwcount dw ? ; READ/WRITEセクタ数
- dskbuffer dd ? ; バッファアドレス
- DSKPACKET ends
- ;
- YES equ 1
- NO equ 0
- OS2 equ -1
- FAT12 equ 0ff7h
- FAT16 equ 0fff7h
- SECTOR32 equ 0000000000000010B
- direntrysize equ 20h
- ;
- extrn sweep:word,sortexec:word,recursive:word,dirgather:word
- extrn dta:dword,srchname:dword,namebuff:dword,namebuffsiz:word
- extrn dirtype:word,fattype:word,attribute:word,clustcount:word
- extrn driveno:word,clustsize:word
- extrn fatbuff:word,dirbuff:word,sortbuff:word,sortcount:word
- extrn drvinf:byte,clustsect:word,sectcount:word,fatdrive:word
- extrn sortfuncs:word,subchain:word,wildcard:byte,pathbuff:byte
- extrn usagemsg:byte,entrycount:word,movecount:word,subsearch:word
- extrn procs:byte,dirover:byte
- extrn bothmsg:byte,sortmsg:byte,movemsg:byte,nothmsg:byte
- extrn errorno:word
- ;
- extrn dos4:word,sect32:word,diskaccs:byte
- ;
- extrn getargs:near,options:near,usageout:near,abort:near,dosstdout:near
- extrn dirlist:near,dirfind:near,strcopywild:near
- extrn dosallocx:near,dirqsort:near,inttoasc0:near
- ;
- PUBLIC main,sortproc,getdirinfo,getdpb,readdirectory,readrootdir,readfat
- PUBLIC getfat12chain,getfat16chain,readsubdir,selection,remainsweep
- PUBLIC copyback,filldeleted,writerootdirectory,writesubdirectory
- PUBLIC dspdirname,dspmsgend,altint23h,critical,breakflag,orgint23h
- ;
- .code
- ;
- ;------------------------------------------------------------------------------
- ; 書き込み時のCtrl+C押下によるディレクトリ破壊を防ぐ処理のワーク
- ;------------------------------------------------------------------------------
- ;
- critical dw NO
- breakflag dw NO
- orgint23h dd 0
- prgname db 'DirSort',0 ; これは別に意味なし
- ;
- ;------------------------------------------------------------------------------
- ;
- ; main
- ; ディレクトリエントリソートユーティリティ メインプログラム
- ;
- ; dsort <options> directory name
- ;
- ; IN ds & es PSP セグメント
- ; OUT ?
- ;
- ;------------------------------------------------------------------------------
- ;
- main proc near
- ;
- call getargs ; コマンド行パラメータを引き数リストに変換
- ; @if (zf,on)
- jnz @i0001
- jmp usageout ; 引き数なしの時はヘルプメッセージ
- ; @ifend
- @i0001:
- push ax
- mov ax,_data ; DS 設定
- mov ds,ax
- ;
- mov ah,30h ; DOS バージョンチェック
- int 21h
- ; @if (al,>=,4),S ; 4.00以上OS/2互換BOX未満ならフラグセット
- cmp al,4
- jb @i0002
- ; @if (al,<,10),S
- cmp al,10
- jae @i0003
- mov dos4,YES
- ; @else
- jmp short @i0004
- @i0003:
- mov dos4,OS2
- ; @ifend
- @i0004:
- ; @else
- jmp short @i0005
- @i0002:
- mov dos4,NO
- ; @ifend
- @i0005:
- ;
- mov ax,1000h ; ディレクトリ名バッファの獲得
- xor dx,dx ; 4KB
- call dosallocx
- mov word ptr namebuff+2,ax
- ;
- mov ax,3523h ; Ctrl+C ベクタ取得
- int 21h
- mov word ptr cs:orgint23h,bx
- mov word ptr cs:orgint23h+2,es
- mov bx,ds ; DS セーブ
- mov es,bx
- mov ax,2523h ; Ctrl+C ベクタ置き換え
- mov dx,offset altint23h ;
- mov bx,cs
- mov ds,bx
- int 21h
- mov bx,es ; DS リストア
- mov ds,bx
- pop ax
- ;
- call options ; 引き数評価&対象ディレクトリリスト作成
- ; @if (sortexec,/=,NO),or,(sweep,/=,NO)
- cmp sortexec,NO
- jne @i0006
- cmp sweep,NO
- je @i0007
- @i0006:
- ; @if (recursive,=,YES) ; 再帰呼び出しをおこなうか?
- cmp recursive,YES
- jne @i0008
- mov es,word ptr namebuff+2
- mov bx,800h ; ディレクトリ名バッファのサイズ変更
- mov ah,4ah ; 32KB
- int 21h
- ; @if (cf,off)
- jc @i0009
- add namebuffsiz,7000h
- ; @ifend
- @i0009:
- ; @ifend
- @i0008:
- push namebuffsiz ; パラメータセット
- push word ptr namebuff
- push word ptr namebuff+2
- xor ax,ax
- push ax
- call sortproc ; ディレクトリソート実行
- ; @ifend
- @i0007:
- ;
- mov ax,2523h ; Ctrl+C ベクタ復元
- lds dx,cs:orgint23h
- int 21h
- ;
- mov ah,0dh ; ディスクバッファ リセット
- int 21h
- ;
- mov ax,4c00h ; プログラム終了
- int 21h
- ;
- main endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; sortproc
- ; ディレクトリソートを実行する
- ;
- ; TYPE near call
- ; IN sp+2:ディレクトリ名リストアドレス
- ; sp+6:ディレクトリ名バッファの空き領域の先頭
- ; sp+8:ディレクトリ名バッファの空き領域サイズ
- ; OUT なし
- ; 保存レジスタ ds
- ;
- ;------------------------------------------------------------------------------
- ;
- sortproc proc near curnameoff,curnameseg,freenameoff,freenamesiz
- ;
- mov di,curnameoff
- mov es,curnameseg
- ; @do until
- @d0001:
- mov entrycount,0 ; 処理したエントリのカウンタを初期化
- mov sortcount,0
- mov movecount,0
- mov ah,0dh ; ディスクバッファ リセット
- int 21h
- ;
- call getdirinfo ; ディレクトリ情報獲得
- ; @if (zf,on),L
- jz @i0010
- jmp @i0011
- @i0010:
- mov di,curnameoff ; ディレクトリ名表示
- mov es,curnameseg
- call dspdirname
- call readdirectory ; ディレクトリ読み込み
- ; @if (zf,on)
- jnz @i0012
- ; @if (sortexec,=,YES),S
- cmp sortexec,YES
- jne @i0013
- call selection ; ソート対象エントリ取り出し
- ; @if (ax,>,1)
- cmp ax,1
- jbe @i0014
- push ds
- mov ax,ds
- mov es,ax
- mov ax,offset sortfuncs
- push ax
- push sortcount
- push sortbuff
- call dirqsort ; クイックソート
- pop ds
- ; @ifend
- @i0014:
- ; @if (sweep,=,YES)
- cmp sweep,YES
- jne @i0015
- call remainsweep ; ソート対象外エントリを掻き集める
- ; @ifend
- @i0015:
- call copyback ; ソートしたエントリを戻す
- ; @else
- jmp short @i0016
- @i0013:
- call predelete
- call remainsweep
- ; @ifend
- @i0016:
- call filldeleted ; 削除エントリの情報をクリアする
- mov cs:critical,YES ; クリティカルセクション開始
- ; @if (dirtype,=,0),S
- cmp dirtype,0
- jne @i0017
- call writerootdirectory ; ルートディレクトリ書き込み
- ; @else
- jmp short @i0018
- @i0017:
- call writesubdirectory ; サブディレクトリ書き込み
- ; @ifend
- @i0018:
- mov es,dirbuff ; ディレクトリバッファの開放
- mov ah,49h
- int 21h
- call dspmsgend ; 終了メッセージ表示
- mov cs:critical,NO ; クリティカルセクション終了
- ; @if (cs:breakflag,=,YES) ; Ctrl+Cが押下されたので終了
- cmp cs:breakflag,YES
- jne @i0019
- mov errorno,-1
- xor cx,cx
- xor dx,dx
- jmp abort
- ; @ifend
- @i0019:
- ; @ifend
- @i0012:
- ; @if (recursive,=,YES) ; 再帰呼び出し
- cmp recursive,YES
- jne @i0020
- mov ah,0dh ; ディスクバッファ リセット
- int 21h
- ;
- mov subsearch,YES ;
- mov di,curnameoff ; サブディレクトリのリスト獲得
- mov es,curnameseg
- call strcopywild
- mov word ptr srchname,di
- mov word ptr srchname+2,es
- call dirlist
- mov ax,word ptr namebuff
- ; @if (ax,/=,freenameoff) ; サブディレクトリ有りの時
- cmp ax,freenameoff
- je @i0021
- push namebuffsiz
- push ax
- push word ptr namebuff+2
- push freenameoff
- call sortproc ; ディレクトリソート再帰実行
- ; @ifend
- @i0021:
- mov si,freenameoff ; 各ワーク情報を再帰実行から戻す
- mov es,freenamesiz
- mov namebuffsiz,es
- mov word ptr namebuff,si
- mov es,curnameseg
- mov word ptr es:[si],0
- mov subsearch,NO ;
- ; @ifend
- @i0020:
- ; @ifend
- @i0011:
- mov di,curnameoff ; 次の対象ディレクトリへ
- mov es,curnameseg
- cld
- xor ax,ax
- mov cx,-1
- repne scasb
- mov curnameoff,di
- ; @doend (byte ptr es:[di],=,0),L ; ディレクトリリストの終了か?
- cmp byte ptr es:[di],0
- je @d0002
- jmp @d0001
- @d0002:
- ;
- ret 8
- ;
- sortproc endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; getdirinfo
- ; ディレクトリ及びその所属するドライブの情報を獲得する
- ;
- ; TYPE near call
- ; IN ds:di = ディレクトリ名
- ; OUT drvinf = DPBのコピー その他 ディレクトリ情報
- ; 保存レジスタ bx,cx,dx,si,di,bp,ds,es
- ;
- ;------------------------------------------------------------------------------
- ;
- getdirinfo proc near
- ;
- call dirfind
- ; @if (zf,on)
- jnz @i0022
- mov dirtype,ax ; ディレクトリタイプ ルート/サブ
- mov subchain,ax ; FATチェインの先頭
- mov driveno,dx ; ドライブ番号
- dec driveno
- ;
- mov di,offset drvinf ; Drive Parameter Block 取得
- call getdpb
- ; @if (zf,on)
- jnz @i0023
- ; @if (drvinf.datasector,<=,4086),S ; 12bitFAT/16bitFAT
- cmp drvinf.datasector,4086
- ja @i0024
- mov fattype,FAT12 ; v1.00バグ '='が無かった
- ; @else
- jmp short @i0025
- @i0024:
- mov fattype,FAT16
- ; @ifend
- @i0025:
- xor ax,ax
- mov al,drvinf.sectorperalloc
- inc ax
- mov clustsect,ax ; 1クラスタ当たりのセクタ数
- mul drvinf.sectorlength
- mov clustsize,ax ; 1クラスタのバイトサイズ
- les bx,drvinf.deviceheader ; デバイスドライバ属性テスト
- ; @if (dos4,=,OS2),or,(es:[bx].deviceattr,on,SECTOR32),S
- cmp dos4,OS2
- je @i0026
- test es:[bx].deviceattr,SECTOR32
- jz @i0027
- @i0026:
- mov sect32,YES ; 32bitセクタ番号サポート
- ; @else
- jmp short @i0028
- @i0027:
- mov sect32,NO
- ; @ifend
- @i0028:
- xor ax,ax
- ; @ifend
- @i0023:
- ; @ifend
- @i0022:
- ret
- ;
- getdirinfo endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; getdpb
- ; ドライブパラメータブロックをコピーする
- ;
- ; TYPE near call
- ; IN dl = ドライブ番号 A:1 B:2 ...
- ; ds:di = drive parameter block をコピーする領域のアドレス
- ; ds:dos4 DOS V4.xx以上フラグ
- ; OUT ax = 完了コード
- ; 保存レジスタ bx,cx,dx,si,di,bp,ds,es
- ;
- ;------------------------------------------------------------------------------
- ;
- getdpb proc near uses bx cx si di ds es
- ;
- cld
- mov ax,ds ; DS セーブ
- mov es,ax
- mov ah,32h ; DPBアドレス取得 非公開
- int 21h
- ; @if (al,=,0),S
- or al,al
- jne @i0029
- mov cx,11h ; DPB コピー 34バイト
- mov si,bx
- push di
- rep movsw ; DPB コピー
- pop di
- ; @if (es:dos4,/=,YES) ; DOS V3.xx以下のときFATセクタ数が1バイトなので
- cmp es:dos4,YES
- je @i0030
- lea si,[bx].D3directorystart ; 後ろに1バイト移動コピーする
- lea di,[di].directorystart
- mov cx,8
- rep movsw
- and es:drvinf.fatsector,0FFH ; 移動後のゴミをクリア
- ; @ifend
- @i0030:
- xor ax,ax
- ; @else
- jmp short @i0031
- @i0029:
- test ax,ax
- ; @ifend
- @i0031:
- ret
- ;
- getdpb endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; readdirectory
- ; ディレクトリを読み込む
- ;
- ; TYPE near call
- ; IN dirtype,driveno,drvinf構造体,fatdrive
- ; OUT ax = 完了コード entrycount,clustcount
- ; 保存レジスタ bx,cx,dx,di,bp,ds
- ;
- ;------------------------------------------------------------------------------
- ;
- readdirectory proc near
- ;
- ; @if (dirtype,=,0),S ; ルートディレクトリ
- cmp dirtype,0
- jne @i0032
- mov ax,drvinf.directoryentry
- mov entrycount,ax ; ディレクトリエントリ数 格納
- call readrootdir
- ; @else
- jmp short @i0033
- @i0032:
- mov ax,driveno ; サブディレクトリ
- ; @if (ax,/=,fatdrive) ; 読み込み済FATと違うドライブ名の時
- cmp ax,fatdrive
- je @i0034
- call readfat ; FAT読み込み
- ; @ifend
- @i0034:
- ;
- cld ; サブディレクトリのクラスタチェインを獲得
- mov di,offset subchain
- mov es,fatbuff
- ; @if (fattype,=,FAT12),S
- cmp fattype,FAT12
- jne @i0035
- call getfat12chain
- ; @else
- jmp short @i0036
- @i0035:
- call getfat16chain
- ; @ifend
- @i0036:
- ; @if (dx,>=,1026),S
- cmp dx,1026
- jb @i0037
- mov ah,9 ; ディレクトリサイズオーバー表示
- mov dx,offset dirover
- int 21h
- mov ax,-1
- ; @else
- jmp short @i0038
- @i0037:
- mov clustcount,dx ; サブディレクトリのクラスタ数を設定
- mov ax,dx
- mul clustsize
- mov cx,32 ; ディレクトリエントリ数 計算 格納
- div cx
- mov entrycount,ax
- call readsubdir ; サブディレクトリ読み込み
- ; @ifend
- @i0038:
- ; @ifend
- @i0033:
- rdirerror:
- test ax,ax
- ret
- ;
- readdirectory endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; readrootdir
- ; ルートディレクトリの内容をメモリに読み込む
- ;
- ; TYPE near call
- ; IN drive parameter block 領域
- ; OUT dirbuff = 読み込んだディレクトリのセグメントアドレス
- ; 保存レジスタ bp,ds,es
- ;
- ;------------------------------------------------------------------------------
- ;
- readrootdir proc near
- local rdsect:word,dirlen:word,buffseg:word,maxrdsect:word
- ;
- mov ax,drvinf.datastartsector ; ディレクトリサイズ計算とメモリ獲得
- sub ax,drvinf.directorystart
- mov sectcount,ax
- mul drvinf.sectorlength
- call dosallocx
- mov dirbuff,ax
- ;
- mov ax,drvinf.directorystart ; ルートディレクトリ読み込み
- mov rdsect,ax ; 読み込み開始セクタ番号
- mov ax,sectcount
- mov dirlen,ax ; 残りディレクトリセクタ数
- mov ax,dirbuff
- mov buffseg,ax ; 読み込みバッファセグメント
- mov dx,1
- xor ax,ax
- div drvinf.sectorlength
- mov maxrdsect,ax ; 64KB当たりのセクタ数
- ; @do while,(dirlen,/=,0) ; 読み込みループ 残りセクタ数0まで
- @d0003:
- cmp dirlen,0
- je @d0004
- mov ax,driveno
- mov cx,maxrdsect
- ; @if (cx,<=,dirlen),S ; 残りセクタ数が64KB以上なら
- cmp cx,dirlen
- ja @i0039
- sub dirlen,cx ; 残りセクタ数を更新
- ; @else ; 64KB未満なら
- jmp short @i0040
- @i0039:
- xor cx,cx ; セクタ数を獲得してワークには0を入れる
- xchg dirlen,cx
- ; @ifend
- @i0040:
- mov dx,rdsect ; 開始セクタ数獲得
- push bp ; 読み込み
- push ds
- ; @if (sect32,=,NO),S ; 従来の16bitセクタ番号
- cmp sect32,NO
- jne @i0041
- xor bx,bx
- mov ds,buffseg
- ; @else ; 新規の32bitセクタ番号
- jmp short @i0042
- @i0041:
- mov bx,offset diskaccs
- mov word ptr [bx].sectornum,dx
- mov word ptr [bx].sectornum+2,0
- mov [bx].rwcount,cx
- mov cx,buffseg
- mov word ptr [bx].dskbuffer,0
- mov word ptr [bx].dskbuffer+2,cx
- mov cx,-1
- ; @ifend
- @i0042:
- int 25h
- ; @if (cf,on)
- jnc @i0043
- xor cx,cx
- xor dx,dx
- jmp abort
- ; @ifend
- @i0043:
- popf
- pop ds
- pop bp
- ;
- mov ax,maxrdsect ; 読み込み開始セクタ数更新
- add rdsect,ax
- add buffseg,1000h ; 読み込みバッファセグメント更新
- ; @doend
- jmp @d0003
- @d0004:
- xor ax,ax
- ret
- ;
- readrootdir endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; readfat
- ; FATを読み込むための領域を獲得し、FATを読み込む
- ;
- ; TYPE near call
- ; IN drive parameter block 領域
- ; OUT fatbuff = 読み込んだFATのセグメントアドレス
- ; 保存レジスタ bp,ds,es
- ;
- ;------------------------------------------------------------------------------
- ;
- readfat proc near
- local rdsect:word,fatlen:word,buffseg:word,maxrdsect:word
- ;
- ; @if (fatdrive,/=,-1) ; 既に別のFATを読み込み済の時、解放する
- cmp fatdrive,-1
- je @i0044
- mov ah,49h ; メモリ解放FUNC 未設定のバグ
- mov es,fatbuff
- int 21h
- mov fatdrive,-1
- mov fatbuff,0
- ; @ifend
- @i0044:
- mov ax,drvinf.fatsector ; FAT用領域獲得
- mul drvinf.sectorlength
- call dosallocx
- mov fatbuff,ax
- ;
- mov ax,driveno ; 128KB BIG-FAT対応
- mov fatdrive,ax
- mov ax,drvinf.reservedsector ; ワーク設定
- mov rdsect,ax ; 読み込み開始セクタ番号
- mov ax,drvinf.fatsector
- mov fatlen,ax ; 残りFATセクタ数
- mov ax,fatbuff
- mov buffseg,ax ; 読み込みバッファセグメント
- mov dx,1
- xor ax,ax
- div drvinf.sectorlength
- mov maxrdsect,ax ; 64KB当たりのセクタ数
- ; @do while,(fatlen,/=,0) ; FAT読み込みループ 残りセクタ数0まで
- @d0005:
- cmp fatlen,0
- je @d0006
- mov ax,driveno
- mov cx,maxrdsect
- ; @if (cx,<=,fatlen),S ; 残りFATセクタ数が64KB以上なら
- cmp cx,fatlen
- ja @i0045
- sub fatlen,cx ; 残りFATセクタ数を更新
- ; @else ; 64KB未満なら
- jmp short @i0046
- @i0045:
- xor cx,cx ; セクタ数を獲得してワークには0を入れる
- xchg fatlen,cx
- ; @ifend
- @i0046:
- mov dx,rdsect ; 開始セクタ数獲得
- push bp ; FAT読み込み
- push ds
- ; @if (sect32,=,NO),S ; 従来の16bitセクタ番号
- cmp sect32,NO
- jne @i0047
- xor bx,bx
- mov ds,buffseg
- ; @else ; 新規の32bitセクタ番号
- jmp short @i0048
- @i0047:
- mov bx,offset diskaccs
- mov word ptr [bx].sectornum,dx
- mov word ptr [bx].sectornum+2,0
- mov [bx].rwcount,cx
- mov cx,buffseg
- mov word ptr [bx].dskbuffer,0
- mov word ptr [bx].dskbuffer+2,cx
- mov cx,-1
- ; @ifend
- @i0048:
- int 25h
- ; @if (cf,on)
- jnc @i0049
- xor cx,cx
- xor dx,dx
- jmp abort
- ; @ifend
- @i0049:
- popf
- pop ds
- pop bp
- ;
- mov ax,maxrdsect ; 読み込み開始セクタ数更新
- add rdsect,ax
- add buffseg,1000h ; 読み込みバッファセグメント更新
- ; @doend
- jmp @d0005
- @d0006:
- ret
- ;
- readfat endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; getfat12chain
- ; 12ビットFATのチェインをたどって、配列に書き出す。
- ;
- ; TYPE near call
- ; IN es:オフセット0= FAT領域
- ; ds:di = FATチェインを書き出す配列、 及びその先頭に最初のクラスタ
- ; 番号を格納しておくこと
- ; OUT dx = チェインの総クラスタ数
- ; 保存レジスタ si,bp,ds,es
- ;
- ;------------------------------------------------------------------------------
- ;
- getfat12chain proc near
- ;
- mov cl,4
- xor dx,dx
- ; @do while,(word ptr [di],<,FAT12),and,(dx,<,1026)
- @d0007:
- cmp word ptr [di],FAT12
- jae @d0008
- cmp dx,1026
- jae @d0008
- mov bx,[di]
- mov ax,bx
- shr ax,1
- add bx,ax
- mov ax,es:[bx]
- ; @if (word ptr [di],off,1),S
- test word ptr [di],1
- jnz @i0050
- and ax,0fffh
- ; @else
- jmp short @i0051
- @i0050:
- shr ax,cl
- ; @ifend
- @i0051:
- lea di,[di+2]
- mov [di],ax
- inc dx
- ; @doend
- jmp @d0007
- @d0008:
- ret
- ;
- getfat12chain endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; getfat16chain
- ; 16ビットFATのチェインをたどって、配列に書き出す。
- ;
- ; TYPE near call
- ; IN es:オフセット0 = FAT領域
- ; ds:di = FATチェインを書き出す配列、 及びその先頭に最初のクラスタ
- ; 番号を格納しておくこと
- ; OUT dx = チェインの総クラスタ数
- ; 保存レジスタ cx,bp,ds
- ;
- ;------------------------------------------------------------------------------
- ;
- getfat16chain proc near
- ;
- mov si,es ; 128KB BIG-FAT対応 FAT領域セグメント退避
- xor dx,dx
- ; @do while,(word ptr [di],<,FAT16),and,(dx,<,1026)
- @d0009:
- cmp word ptr [di],FAT16
- jae @d0010
- cmp dx,1026
- jae @d0010
- mov bx,[di]
- shl bx,1
- ; @if (cf,off),S ; 最初の64KB
- jc @i0052
- mov es,si
- ; @else ; 次の64KB
- jmp short @i0053
- @i0052:
- lea ax,[si+1000h]
- mov es,ax
- ; @ifend
- @i0053:
- mov ax,es:[bx] ; FATチェインの獲得
- lea di,[di+2]
- mov [di],ax
- inc dx
- ; @doend
- jmp @d0009
- @d0010:
- ret
- ;
- getfat16chain endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; readsubdir
- ; サブディレクトリを読み込む
- ;
- ; TYPE near call
- ; IN clustcount ディレクトリのクラスタ数
- ; OUT dirbuff = 読み込んだディレクトリのセグメントアドレス
- ; 保存レジスタ cx,si,bp,ds,es
- ;
- ;------------------------------------------------------------------------------
- ;
- readsubdir proc near
- local cluster:word,clustseg:word
- ;
- mov dx,clustcount ; ディレクトリサイズ計算
- mov cluster,dx
- mov ax,clustsect
- mul dx
- mul drvinf.sectorlength
- call dosallocx ; ディレクトリバッファ獲得
- mov dirbuff,ax
- mov ax,clustsize
- mov cl,4
- shr ax,cl
- mov clustseg,ax
- xor bx,bx
- mov di,offset subchain ; ディレクトリクラスタチェインの先頭
- ;
- ; @if (sect32,=,NO)
- cmp sect32,NO
- jne @i0054
- push ds
- mov ax,ds
- mov es,ax
- mov ds,dirbuff
- ; @do until
- @d0011:
- mov ax,es:[di] ; ディレクトリクラスタ読み込み
- sub ax,2
- mov cx,es:clustsect
- mul cx
- add ax,es:drvinf.datastartsector
- mov dx,ax
- mov ax,es:driveno
- push bp
- push di
- int 25h
- ; @if (cf,on)
- jnc @i0055
- xor cx,cx
- xor dx,dx
- jmp abort
- ; @ifend
- @i0055:
- popf
- pop di
- pop bp
- mov ax,ds
- add ax,clustseg ; 次のバッファセグメント
- mov ds,ax
- lea di,[di+2] ; 次のクラスタ
- dec cluster ; カウントダウン
- ; @doend (zf,on)
- jnz @d0011
- pop ds
- ; @else
- jmp @i0056
- @i0054:
- mov ax,clustsect
- mov diskaccs.rwcount,ax
- mov ax,dirbuff
- mov word ptr diskaccs.dskbuffer,0
- mov word ptr diskaccs.dskbuffer+2,ax
- ; @do until
- @d0012:
- mov bx,offset diskaccs
- mov ax,[di] ; ディレクトリクラスタ読み込み
- sub ax,2
- mov cx,clustsect
- mul cx
- add ax,drvinf.datastartsector
- adc dx,0
- mov word ptr [bx].sectornum,ax
- mov word ptr [bx].sectornum+2,dx
- mov ax,driveno
- mov cx,-1
- push bp
- push di
- int 25h
- ; @if (cf,on)
- jnc @i0057
- xor cx,cx
- xor dx,dx
- jmp abort
- ; @ifend
- @i0057:
- popf
- pop di
- pop bp
- mov ax,clustseg
- add word ptr diskaccs.dskbuffer+2,ax ; 次のバッファセグメント
- lea di,[di+2] ; 次のクラスタ
- dec cluster ; カウントダウン
- ; @doend (zf,on)
- jnz @d0012
- ; @ifend
- @i0056:
- xor ax,ax
- ret
- ;
- readsubdir endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; selection
- ; 読み込んだディレクトリからattributeで指定されたエントリを選択して
- ; ソートバッファに移動する
- ;
- ; TYPE near call
- ; IN dirbuff = 読み込んだディレクトリのセグメントアドレス その他
- ; OUT sortbuff = ソート対象を選択・移動したセグメントアドレス
- ; 保存レジスタ bp,ds
- ;
- ;------------------------------------------------------------------------------
- ;
- selection proc near
- ;
- mov ax,direntrysize ; ディレクトリサイズからバッファサイズ
- mul entrycount ;
- call dosallocx ; ソートバッファ獲得
- mov sortbuff,ax
- mov es,ax
- mov bx,attribute ; 選出属性
- mov dx,entrycount ; エントリ数
- mov si,dirbuff
- ; @if (dirtype,/=,0) ; サブディレクトリの時は最初の2つを除外
- cmp dirtype,0
- je @i0058
- sub dx,2
- lea si,[si+4]
- ; @ifend
- @i0058:
- ;
- push ds
- cld
- xor ax,ax
- mov ds,si
- ; @do while,(dx,/=,0),and,(byte ptr ds:[0],/=,0)
- @d0013:
- or dx,dx
- je @d0014
- cmp byte ptr ds:[0],0
- je @d0014
- ; @cbegin
- ; @case (byte ptr ds:[0],=,0e5h),S ; 削除エントリか?
- cmp byte ptr ds:[0],0e5h
- jne @c0002
- mov byte ptr ds:[0],0 ; 後の処理のために0を書いておく
- ; @case (byte ptr ds:[0bh],on,bl),S ; 属性違いか?
- jmp short @c0001
- @c0002:
- test byte ptr ds:[0bh],bl
- jz @c0003
- ; @other ; ソートバッファへ移動
- jmp short @c0001
- @c0003:
- mov cx,10h
- xor si,si
- xor di,di
- rep movsw
- mov byte ptr ds:[0],0 ; 移動元に0を書いておく
- ; @if (byte ptr es:[0],=,5) ; 名前の頭がE5用のコードなら戻しておく
- cmp byte ptr es:[0],5
- jne @i0059
- mov byte ptr es:[0],0e5h
- ; @ifend
- @i0059:
- mov si,es
- lea si,[si+2]
- mov es,si
- inc ax ; 移動したエントリ数を加算
- ; @cend
- @c0001:
- mov si,ds
- lea si,[si+2]
- mov ds,si
- dec dx ; カウントダウン
- ; @doend
- jmp @d0013
- @d0014:
- pop ds
- mov sortcount,ax ; 移動したエントリ数を記録
- ret
- ;
- selection endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; predelete
- ; 後のremainsweepルーチンのために削除エントリの先頭を00とする
- ;
- ; TYPE near call
- ; IN entrycount,dirbuff
- ; OUT なし
- ; 保存レジスタ ax,bx,dx,si,bp,ds
- ;
- ;------------------------------------------------------------------------------
- ;
- predelete proc near
- ;
- mov cx,entrycount
- mov di,dirbuff
- ; @do until
- @d0015:
- mov es,di
- ; @if (byte ptr es:[0],=,0e5h)
- cmp byte ptr es:[0],0e5h
- jne @i0060
- mov byte ptr es:[0],0
- ; @ifend
- @i0060:
- lea di,[di+2]
- dec cx
- ; @doend (zf,on)
- jnz @d0015
- ret
- ;
- predelete endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; remainsweep
- ; ソート対象外のエントリをディレクトリバッファの先頭に集める
- ;
- ; TYPE near call
- ; IN entrycount,dirbuff
- ; OUT movecount
- ; 保存レジスタ ax,bp,ds
- ;
- ;------------------------------------------------------------------------------
- ;
- remainsweep proc near
- ;
- cld
- push ds
- xor bx,bx
- mov dx,entrycount ; ディレクトリのエントリサイズ
- mov ds,dirbuff
- mov di,ds ; 最初の空きエントリ位置取得
- ; @do while,(byte ptr ds:[0],/=,0),and,(dx,/=,0)
- @d0016:
- cmp byte ptr ds:[0],0
- je @d0017
- or dx,dx
- je @d0017
- lea di,[di+2]
- mov ds,di
- dec dx
- ; @doend
- jmp @d0016
- @d0017:
- mov es,di
- ; @do until
- @d0018:
- mov di,ds ; 次の有効エントリ位置取得
- ; @do while,(byte ptr ds:[0],=,0),and,(dx,/=,0)
- @d0019:
- cmp byte ptr ds:[0],0
- jne @d0020
- or dx,dx
- je @d0020
- lea di,[di+2]
- mov ds,di
- dec dx
- ; @doend
- jmp @d0019
- @d0020:
- ; @if (dx,/=,0) ; 終了でなければエントリを頭へ詰める
- or dx,dx
- je @i0061
- inc bx
- mov cx,10h
- xor si,si
- xor di,di
- rep movsw
- mov byte ptr ds:[0],0 ; 移動元を空きエントリとする
- mov di,es
- ; @do while,(byte ptr es:[0],/=,0) ; 次の空きエントリ位置取得
- @d0021:
- cmp byte ptr es:[0],0
- je @d0022
- lea di,[di+2]
- mov es,di
- ; @doend
- jmp @d0021
- @d0022:
- ; @ifend
- @i0061:
- ; @doend (dx,=,0)
- or dx,dx
- jne @d0018
- pop ds
- mov movecount,bx ; 移動したエントリ数を記録
- ret
- ;
- remainsweep endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; copyback
- ; ソートバッファの内容をディレクトリバッファへ書き戻す
- ;
- ; TYPE near call
- ; IN sortcount,sortbuff,dirbuff
- ; OUT dirbuff
- ; 保存レジスタ bx,bp,ds
- ;
- ;------------------------------------------------------------------------------
- ;
- copyback proc near uses ds
- ;
- cld
- mov dx,sortcount ; ソートバッファ上のエントリ数
- mov es,dirbuff
- mov ds,sortbuff
- ; @do while,(dx,/=,0)
- @d0023:
- or dx,dx
- je @d0024
- ; @if (byte ptr es:[0],=,0),S ; ディレクトリバッファは空きエントリ?
- cmp byte ptr es:[0],0
- jne @i0062
- ; @if (byte ptr ds:[0],=,0e5h) ; 名前の頭がE5なら、変換しておく
- cmp byte ptr ds:[0],0e5h
- jne @i0063
- mov byte ptr ds:[0],05h
- ; @ifend
- @i0063:
- mov cx,10h ; コピー
- xor si,si
- xor di,di
- rep movsw
- dec dx ; カウントダウン
- mov si,ds ; 次のソートバッファエントリへ
- lea si,[si+2]
- mov ds,si
- ; @ifend
- @i0062:
- mov si,es ; 次のディレクトリバッファエントリへ
- lea si,[si+2]
- mov es,si
- ; @doend
- jmp @d0023
- @d0024:
- ;
- mov ax,seg sortbuff ; ソートバッファの解放
- mov ds,ax
- mov es,sortbuff
- mov ah,49h
- int 21h
- ;
- ret
- ;
- copyback endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; filldeleted
- ; ディレクトリ中の削除エントリをクリアする
- ;
- ; TYPE near call
- ; IN entrycount,dirbuff
- ; OUT なし
- ; 保存レジスタ bx,bp,ds
- ;
- ;------------------------------------------------------------------------------
- ;
- filldeleted proc near
- ;
- cld
- mov ax,0f6h ; 埋め込みデータの設定
- mov si,entrycount ; ディレクトリの最終ポイント取得
- mov dx,si
- shl dx,1
- add dx,dirbuff
- ; @do until
- @d0025:
- sub dx,2 ; 最終位置から先頭方向へ
- mov es,dx
- ; @if (byte ptr es:[0],=,0),S ; 削除エントリ判定
- cmp byte ptr es:[0],0
- jne @i0064
- mov es:[0],ah ; 頭1バイト 0orE5
- mov cx,1fh ; 残り31バイトをF6で埋める
- mov di,1
- rep stosb
- ; @else ; 有効エントリが見つかったので
- jmp short @i0065
- @i0064:
- mov ah,0e5h ; それ以後は頭1バイトをE5に変更
- ; @ifend
- @i0065:
- dec si
- ; @doend (si,=,0) ; ディレクトリ先頭になるまで
- or si,si
- jne @d0025
- ret
- ;
- filldeleted endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; writerootdirectory
- ; ルートディレクトリバッファをファイルに書き戻す
- ;
- ; TYPE near call
- ; IN dirtype,driveno,drvinf構造体,sectcount,clustcount,dirbuff
- ; clustsect,clustsize,subchain
- ; OUT なし
- ; 保存レジスタ
- ;
- ;------------------------------------------------------------------------------
- ;
- writerootdirectory proc near
- local wtsect:word,dirlen:word,buffseg:word,maxwtsect:word
- ;
- mov ax,drvinf.directorystart ; ルートディレクトリ書き込み
- mov wtsect,ax ; 書き込み開始セクタ番号
- mov ax,sectcount
- mov dirlen,ax ; 残りディレクトリセクタ数
- mov ax,dirbuff
- mov buffseg,ax ; 書き込みバッファセグメント
- mov dx,1
- xor ax,ax
- div drvinf.sectorlength
- mov maxwtsect,ax ; 64KB当たりのセクタ数
- ; @do while,(dirlen,/=,0) ; 書き込みループ 残りセクタ数0まで
- @d0026:
- cmp dirlen,0
- je @d0027
- mov ax,driveno
- mov cx,maxwtsect
- ; @if (cx,<=,dirlen),S ; 残りセクタ数が64KB以上なら
- cmp cx,dirlen
- ja @i0066
- sub dirlen,cx ; 残りセクタ数を更新
- ; @else ; 64KB未満なら
- jmp short @i0067
- @i0066:
- xor cx,cx ; セクタ数を獲得してワークには0を入れる
- xchg dirlen,cx
- ; @ifend
- @i0067:
- mov dx,wtsect ; 開始セクタ数獲得
- push bp ; 書き込み
- push ds
- ; @if (sect32,=,NO),S ; 従来の16bitセクタ番号
- cmp sect32,NO
- jne @i0068
- xor bx,bx
- mov ds,buffseg
- ; @else ; 新規の32bitセクタ番号
- jmp short @i0069
- @i0068:
- mov bx,offset diskaccs
- mov word ptr [bx].sectornum,dx
- mov word ptr [bx].sectornum+2,0
- mov [bx].rwcount,cx
- mov cx,buffseg
- mov word ptr [bx].dskbuffer,0
- mov word ptr [bx].dskbuffer+2,cx
- mov cx,-1
- ; @ifend
- @i0069:
- int 26h
- ; @if (cf,on)
- jnc @i0070
- xor cx,cx
- xor dx,dx
- jmp abort
- ; @ifend
- @i0070:
- popf
- pop ds
- pop bp
- ;
- mov ax,maxwtsect ; 書き込み開始セクタ数更新
- add wtsect,ax
- add buffseg,1000h ; 書き込みバッファセグメント更新
- ; @doend
- jmp @d0026
- @d0027:
- ret
- ;
- writerootdirectory endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; writesubdirectory
- ; サブディレクトリバッファをファイルに書き戻す
- ;
- ; TYPE near call
- ; IN dirtype,driveno,drvinf構造体,sectcount,clustcount,dirbuff
- ; clustsect,clustsize,subchain
- ; OUT なし
- ; 保存レジスタ
- ;
- ;------------------------------------------------------------------------------
- ;
- writesubdirectory proc near
- local cluster:word,clustseg:word
- ;
- push ds ; サブディレクトリ書き込み
- mov ax,clustcount
- mov cluster,ax
- mov ax,clustsize
- mov cl,4
- shr ax,cl
- mov clustseg,ax
- mov di,offset subchain
- ; @if (sect32,=,NO)
- cmp sect32,NO
- jne @i0071
- mov ax,ds
- mov es,ax
- xor bx,bx
- mov ds,dirbuff
- ; @do until
- @d0028:
- mov ax,es:[di]
- sub ax,2
- mov cx,es:clustsect
- mul cx
- add ax,es:drvinf.datastartsector
- mov dx,ax
- mov ax,es:driveno
- push bp
- push di
- int 26h
- ; @if (cf,on)
- jnc @i0072
- xor cx,cx
- xor dx,dx
- jmp abort
- ; @ifend
- @i0072:
- popf
- pop di
- pop bp
- mov ax,ds
- add ax,clustseg
- mov ds,ax
- lea di,[di+2]
- dec cluster
- ; @doend (zf,on)
- jnz @d0028
- pop ds
- ; @else
- jmp @i0073
- @i0071:
- mov ax,clustsect
- mov diskaccs.rwcount,ax
- mov ax,dirbuff
- mov word ptr diskaccs.dskbuffer,0
- mov word ptr diskaccs.dskbuffer+2,ax
- ; @do until
- @d0029:
- mov bx,offset diskaccs
- mov ax,[di] ; ディレクトリクラスタ書き込み
- sub ax,2
- mov cx,clustsect
- mul cx
- add ax,drvinf.datastartsector
- adc dx,0
- mov word ptr [bx].sectornum,ax
- mov word ptr [bx].sectornum+2,dx
- mov ax,driveno
- mov cx,-1
- push bp
- push di
- int 26h
- ; @if (cf,on)
- jnc @i0074
- xor cx,cx
- xor dx,dx
- jmp abort
- ; @ifend
- @i0074:
- popf
- pop di
- pop bp
- mov ax,clustseg
- add word ptr diskaccs.dskbuffer+2,ax ; 次のバッファセグメント
- lea di,[di+2] ; 次のクラスタ
- dec cluster ; カウントダウン
- ; @doend (zf,on)
- jnz @d0029
- ; @ifend
- @i0073:
- ret
- ;
- writesubdirectory endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; dspdirname
- ; 処理中ディレクトリ名を表示する
- ;
- ; TYPE near call
- ; IN ES:DI ディレクトリ名文字列アドレス
- ; OUT なし
- ; 保存レジスタ DS
- ;
- ;------------------------------------------------------------------------------
- ;
- dspdirname proc
- ;
- mov ah,9 ; 処理中メッセージ表示
- mov dx,offset procs
- int 21h
- ;
- cld ; ディレクトリ名長さを獲得
- mov cx,-1
- xor ax,ax
- mov dx,di
- repne scasb
- not cx
- dec cx
- ;
- push ds ; ディレクトリ名表示
- mov ax,es
- mov ds,ax
- call dosstdout
- pop ds
- ;
- mov ah,2 ; 行頭への復帰
- mov dl,0dh
- int 21h
- ;
- ret
- ;
- dspdirname endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; dspmsgend
- ; 処理終了メッセージを表示する
- ;
- ; TYPE near call
- ; IN sortcount,movecount,sortproc,sweep
- ; OUT なし
- ; 保存レジスタ ax,bx,cx,dx,si,di,bp,ds,es
- ;
- ;------------------------------------------------------------------------------
- ;
- dspmsgend proc uses ax bx cx dx si di ds es
- local wrks:dword,wrka:word
- ;
- mov ax,sortcount ; ソートしたエントリ数
- mov bx,movecount ; 移動したエントリ数
- mov cx,ax
- add cx,bx
- ; @cbegin
- ; @case (sortexec,=,YES),and,(sweep,=,YES),and,(cx,/=,0),S ; ソート&移動
- cmp sortexec,YES
- jne @c0005
- cmp sweep,YES
- jne @c0005
- or cx,cx
- je @c0005
- mov ax,cx
- mov si,offset bothmsg
- ; @case (sortexec,=,YES),and,(sweep,=,NO),and,(ax,/=,0),S ; ソートのみ
- jmp short @c0004
- @c0005:
- cmp sortexec,YES
- jne @c0006
- cmp sweep,NO
- jne @c0006
- or ax,ax
- je @c0006
- ; @if (ax,>,1),S
- cmp ax,1
- jbe @i0075
- mov si,offset sortmsg ; 2つ以上ならソートのみ表示
- ; @else
- jmp short @i0076
- @i0075:
- mov si,offset bothmsg ; 1つだけならソート&移動表示
- ; @ifend
- @i0076:
- ; @case (sortexec,=,NO),and,(sweep,=,YES),and,(bx,/=,0),S ; 移動のみ
- jmp short @c0004
- @c0006:
- cmp sortexec,NO
- jne @c0007
- cmp sweep,YES
- jne @c0007
- or bx,bx
- je @c0007
- mov ax,cx
- mov si,offset movemsg ; 移動
- ; @other
- jmp short @c0004
- @c0007:
- xor ax,ax
- mov si,offset nothmsg ; 対象なし
- ; @cend
- @c0004:
- ; @if (ax,/=,0)
- or ax,ax
- je @i0077
- mov di,ss ; 処理したエントリ数表示
- mov es,di
- lea di,offset wrka+1
- call inttoasc0
- lea di,[di-5] ; 0サプレス処理
- push di
- mov cx,4
- ; @do while,(byte ptr es:[di],=,'0'),and,(cx,/=,0)
- @d0030:
- cmp byte ptr es:[di],'0'
- jne @d0031
- or cx,cx
- je @d0031
- mov byte ptr es:[di],' '
- inc di
- dec cx
- ; @doend
- jmp @d0030
- @d0031:
- mov cx,5 ; エントリ数表示
- pop dx
- mov di,ds
- push ss
- pop ds
- call dosstdout
- mov ds,di
- ; @ifend
- @i0077:
- mov ah,9 ; エントリ数に続くメッセージ表示
- mov dx,si
- int 21h
- ret
- ;
- dspmsgend endp
- ;
- ;------------------------------------------------------------------------------
- ;
- ; altint23h
- ; Ctrl+C押下の横取り
- ;
- ; TYPE interrupt
- ; IN なし
- ; OUT なし
- ; 保存レジスタ ax,bx,cx,dx,si,di,bp,ds,es
- ;
- ;------------------------------------------------------------------------------
- ;
- altint23h proc
- ;
- ; @if (cs:critical,=,NO),S ; クリティカルセクションではない時
- cmp cs:critical,NO
- jne @i0078
- jmp cs:orgint23h ; 既存の終了処理へ
- ; @else ; クリティカルセクションの時
- jmp short @i0079
- @i0078:
- mov cs:breakflag,YES ; Ctrl+C押下を記憶しただけで復帰
- iret
- ; @ifend
- @i0079:
- ;
- altint23h endp
- ;
- end main